package com.zsrt.common;

import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;

/**
 * 处理控制层controller map的处理
 * 怎么把一个类声明为一个切面?
 * step1: 需要把这个类纳入到spring ioc容器的管理  @Component
 * step2: 需要把这个类声明为一个切面 @Aspect
 * step3: 需要告诉spring invokeBeforeMethod这个方法需要在哪些类的哪些方法开始之前执行
 * 		  @Before注解 用来说明该方法是一个前置通知[在目标方法开始之前执行]
 * 		  切点表达式
 * step4: 在applicationContext.xml中增加配置使得前置通知@Before起作用
 * 
 * step5: 如何接收到方法的参数 Joinpoint jp
 * 
 * @author scott
 *
 */

//@Component
//@Aspect
//@Order(1)
public class MapExceptionAspect {
	
	
	public MapExceptionAspect(){
		System.out.println("初始化MapExceptionAspect....");
	}
	
	
	/**
	 * 环绕通知  相当于前面4种通知的的集合 或者说是
	 * 环绕通知类似于动态代理的全过程。
	 * 
	 * 重点注意： 环绕通知 需要携带参数： ProceedingJoinPoint pjp  而且环绕通知必须要有返回值。返回值即为目标方法的返回值
	 * 
	 * 参数pjp 可以决定是否执行目标方法  
	 */
	@SuppressWarnings("unchecked")
	//@Around("execution(* com.zsrt.easyui.user.controller.UserController.update(..))")
	public Object invokeAround(ProceedingJoinPoint pjp){
		
		Signature sign = pjp.getSignature();
		//得到方法的名字
		String name = sign.getName();
		
		//得到方法的参数
		Object[] args = pjp.getArgs();
		System.out.println(args.length);
		System.out.println(args[1].getClass().getName());
		List<Object> as = Arrays.asList(args);
		
		Map<String,Object> map = (Map<String,Object>)args[0];
		
		System.out.println("[环绕通知 ]方法"+name+"的参数是"+as);
		
		Object obj = null;
		
		//执行目标方法...
		try {
			System.out.println("[模拟 前置通知] ...");
			Map<String,Object> reuslt = new HashMap<String,Object>();
			
			obj = pjp.proceed();
			reuslt=(Map<String, Object>) obj;
			System.out.println("[模拟 返回通知] ...");
			map.put("code", "success");
			map.put("msg", "操作成功 aop1...");
			
			reuslt.put("code", "success");
			reuslt.put("msg", "操作成功 aop2...");
			System.out.println("obj="+obj);
		} catch (Throwable e) {
			map.put("code", "failure");
			map.put("msg", "操作失败 aop...");
			System.out.println("[模拟 异常通知] ...");
			e.printStackTrace();
		}
		System.out.println("[模拟 后置通知] ...");
		return obj;
	}

}
